﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using NLog;
using dlCentral.PluginHandlers;
using dlCentral.Settings;
using dlCentral.Settings.Data;
using Cornerstone.Tools;

namespace dlCentral.Utils {
    public static class dlCentralUtils {
        private static Logger logger = LogManager.GetCurrentClassLogger();
        public static readonly string SettingsFileName = "dlCentral.xml";
        public static string LogFileName = "dlCentral.log";
        public static string OldLogFileName = "dlCentral.log.bak";
        private static readonly object syncRoot = new object();

        public static List<string> ProtocolTypes = new List<string> { "FTP", "FTPSI", "FTPSE", "FTPTE",
                                                                      "SFTP", "SCP" };
        public static List<string> ProtocolStrings = new List<string> { "FTP", "FTP SSL/TLS Implicit", "FTP SSL Explicit", "FTP TLS Explicit",
                                                                      "SFTP ", "SCP"};

        public static List<string> SiteTypes = new List<string> { "FTP", "Torrent"};
        public static List<string> SiteTypeStrings = new List<string> { "FTP", "Torrent" };


 
        public static string PluginName() {
            if (SettingsManager.Properties == null || SettingsManager.Properties.GUISettings == null) return "dlCentral";
            return string.IsNullOrEmpty(SettingsManager.Properties.GUISettings.PluginName) ? "dlCentral" : SettingsManager.Properties.GUISettings.PluginName;
        }

        public static bool isImdbIdCorrect(string imdbId) {
            if (string.IsNullOrEmpty(imdbId)) return false;

            return imdbId.Length == 9 && Regex.Match(imdbId, @"tt\d{7}").Success;
        }

        public static bool isYearCorrect(string year) {
            if (string.IsNullOrEmpty(year)) return false;

            //bool result = year.Length == 4 && Regex.Match(year, @"\d{4}").Success;

            //if (result) {
            int intYear = -1;
            if (int.TryParse(year, out intYear)) {
                if (intYear < 1900 || intYear > yearToRange()) {
                    return false;
                }
            }
            else {
                return false;
            }

            return true;
        }

        public static int yearToRange() {
            //return System.DateTime.Now.Year + 100;
            // TODO MS
            return 2050;
        }

        public static bool isSeasonOrEpisodeCorrect(string seasonOrEpisode) {
            if (string.IsNullOrEmpty(seasonOrEpisode)) return false;

            //bool result = seasonOrEpisode.Length > 0 && seasonOrEpisode.Length < 4 && Regex.Match(seasonOrEpisode, @"\d{1,3}").Success;

            //if (result) {
            int intSeasonOrEpisode = -1;
            if (int.TryParse(seasonOrEpisode, out intSeasonOrEpisode)) {
                if (intSeasonOrEpisode < 0 || intSeasonOrEpisode > 999) {
                    return false;
                }
            }
            else {
                return false;
            }

            return true;
        }

        public static bool IsAssemblyAvailable(string name, Version ver) {
            return IsAssemblyAvailable(name, ver, false);
        }

        public static bool IsAssemblyAvailable(string name, Version ver, bool reflectionOnly) {
            Assembly[] assemblies = null;

            if (!reflectionOnly) 
                assemblies = AppDomain.CurrentDomain.GetAssemblies();
            else
                assemblies = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies();

            if (assemblies != null) {
                foreach (Assembly a in assemblies) {
                    try {
                        if (a.GetName().Name == name && a.GetName().Version >= ver)
                            return true;
                    }
                    catch (Exception e) {
                        logger.ErrorException(string.Format("Assembly.GetName() call failed for '{0}'!\n", a.Location), e);
                    }
                }
            }

            return false;
        }

        public static bool IsValidAlphaNumeric(string inputStr) {
            if (string.IsNullOrEmpty(inputStr))
                return false;

            for (int i = 0; i < inputStr.Length; i++) {
                if (!(char.IsLetter(inputStr[i])) && (!(char.IsNumber(inputStr[i]))))
                    return false;
            }
            return true;
        }

        public static string TrimNonAlphaNumeric(string inputStr) {
            string result = string.Empty;

            if (string.IsNullOrEmpty(inputStr))
                return result;

            for (int i = 0; i < inputStr.Length; i++) {
                if (char.IsLetter(inputStr[i]) || char.IsNumber(inputStr[i]))
                    result += inputStr[i];
            }
            return result;
        }

        public static string GetModifiedTVSeries(string inputStr)
        {
            string result = inputStr;

            if (string.IsNullOrEmpty(inputStr))
                return result;

            foreach (TVSeries tvseries in Settings.SettingsManager.Properties.TVSeriesSettings.TVseries)
            {
                if (tvseries.OriginalName == inputStr) result = tvseries.ModifiedName;
            }
            return result;
        }

        public static string GetSeparatorTVSeries(string inputStr)
        {
            string result = Settings.SettingsManager.Properties.TVSeriesSettings.DefaultSeparator;

            if (string.IsNullOrEmpty(inputStr))
                return result;

            foreach (TVSeries tvseries in Settings.SettingsManager.Properties.TVSeriesSettings.TVseries)
            {
                if (tvseries.OriginalName == inputStr) result = tvseries.Separator;
            }
            return result;
        }

        public static string GetSeasonFormatTVSeries(string inputStr)
        {
            string result = Settings.SettingsManager.Properties.TVSeriesSettings.DefaultSeasonFormat;

            if (string.IsNullOrEmpty(inputStr))
                return result;

            foreach (TVSeries tvseries in Settings.SettingsManager.Properties.TVSeriesSettings.TVseries)
            {
                if (tvseries.OriginalName == inputStr) result = tvseries.SeasonFormat;
            }
            return result;
        }

        public static string GetEpisodeFormatTVSeries(string inputStr)
        {
            string result = Settings.SettingsManager.Properties.TVSeriesSettings.DefaultEpisodeFormat;

            if (string.IsNullOrEmpty(inputStr))
                return result;

            foreach (TVSeries tvseries in Settings.SettingsManager.Properties.TVSeriesSettings.TVseries)
            {
                if (tvseries.OriginalName == inputStr) result = tvseries.EpisodeFormat;
            }
            return result;
        }

        public static WebGrabber GetWebGrabberInstance(string url)
        {
            WebGrabber grabber = new WebGrabber(url);
            grabber.UserAgent = "dlCentral/" + Assembly.GetExecutingAssembly().GetName().Version.ToString();
            return grabber;
        }
        // Separates the year from the title string (if applicable)
        public static string extractYearFromTitle(string input, out int year)
        {
            string rtn = input;
            year = 0;

            // if there is a four digit number that looks like a year, parse it out
            Regex expr = new Regex(@"^(.*)[\[\(]?(19\d{2}|20\d{2})[\]\)]?($|.+)");
            Match match = expr.Match(rtn);
            if (match.Success)
            {
                rtn = match.Groups[1].Value.TrimEnd('(', '[','.'); // leading title string
                year = int.Parse(match.Groups[2].Value);
                if (rtn.Trim() == string.Empty)
                    rtn = match.Groups[3].Value.TrimEnd('(', '[','.'); // trailing title string
            }

            // If the title becomes 0 length, undo this method's processing.
            if (rtn.Trim().Length == 0) { rtn = input; year = 0; return rtn; } else { return rtn.Trim(); }
        }

        public static string extractTitle(string input)
        {
            string rtn = input;
 
            // if there is a four digit number that looks like a year, parse it out
            Regex expr = new Regex(@"^(.*)[\[\(]?(1080\D{1}|720\D{1})[\]\)]?($|.+)");
            Match match = expr.Match(rtn);
            if (match.Success)
            {
                rtn = match.Groups[1].Value.TrimEnd('(', '[', '.'); // leading title string
                if (rtn.Trim() == string.Empty)
                    rtn = match.Groups[3].Value.TrimEnd('(', '[', '.'); // trailing title string
            }

            // If the title becomes 0 length, undo this method's processing.
            if (rtn.Trim().Length == 0) { rtn = input; return rtn; } else { return rtn.Trim(); }
        }
        public static string RemoveGarbage(string input)
        {
            string rtn = input;
            rtn = rtn.Replace("REAL.PROPER", "");
            rtn = rtn.Replace("REAL PROPER", "");
            rtn = rtn.Replace("REPACK", "");
            rtn = rtn.Replace("LIMITED", "");
            rtn = rtn.Replace("PROPER", "");
            rtn = rtn.Replace("UNRATED", "");
            rtn = rtn.Replace("EXTENDED.CUT", "");
            rtn = rtn.Replace("EXTENDED CUT", ""); 

            rtn = rtn.Replace(".", " ");
            rtn = rtn.TrimEnd(' ');
            return rtn;
        }

        public static string FormatByteSize(Int64 bytes)
        {
          Int64 B = 1; //byte
          Int64 KB = 1024 * B; //kilobyte
          Int64 MB = 1024 * KB; //megabyte
          Int64 GB = 1024 * MB; //gigabyte
          string result = "";  
          if (bytes > GB)
              result = string.Format("{0:0.##} GB", (float)bytes / GB);
          else
            if (bytes > MB)
                result = string.Format("{0:0.##} MB", (float)bytes / MB);
            else
              if (bytes > KB)
                  result = string.Format("{0:0.##} KB", (float)bytes / KB);
              else
                  result = string.Format("{0:0.##} bytes", (float)bytes);
          return result;
        }
    }

}
